// =====================================================================================
// 
//       Filename:  pathutils.c
// 
//    Description:  Implementation of functions operating on path names
// 
//        Version:  1.0
//        Created:  03/10/2010 14:47:05
//       Revision:  none
//       Compiler:  g++
// 
//         Author:  François Hissel (fh), francois.hissel@m4x.org
//        Company:  
// 
// =====================================================================================

#include	<stdlib.h>
#include	<string.h>
#include	<unistd.h>
#include	"filecaching.h"
#include	"pathutils.h"

#define num_html_entities 19
const char *html_entities[num_html_entities]={"eacute","egrave","ecirc","euml","agrave","acirc","auml","icirc","iuml","ugrave","ucirc","uml","ocirc","ouml","ccedil","amp","lt","gt","quot"};
const char *utf_symbols[num_html_entities]={"é","è","ê","ë","à","â","ä","î","ï","ù","û","ü","ô","ö","ç","&","<",">","'"};

void path_simplify(const char *pathname,char *newname) {
	int parent=0;	// Number of ".." in the path
	const char *p=pathname;	// Position in the initial path
	char *q;	// Position in the temporary path
	const char *r;
	while (*p) ++p;
	char temp[p-pathname];
	q=temp+(p-pathname);
	while (p>=pathname) {
		r=p-1;
		while (r>=pathname && (*r!='/' || (r!=pathname && *(r-1)=='\\'))) --r;	// Now r points to the last separator
		if (p-r==2 && *(r+1)=='.') p=r;	// Just ignore '.' directory
		else if (p-r==3 && *(r+1)=='.' && *(r+2)=='.') {++parent; p=r;}	// If '..' directory, increase the parent counter
		else {	// If it is a standard name
			if (parent>0) --parent;	// We are still accessing to a parent directory
			else {	// Well this is a standard name, we can add it at the end of the path
				q-=(p-r-1);
				strncpy(q,r+1,p-r);
				--q;
			}
			p=r;
		}
	}
	// Now copy the temporary path in the output buffer
	++q;
	char *t=newname;
	while (*q!=0) *(t++)=*(q++);
	*t=0;
}

void get_dir(const char **pathname,char *name) {
	if (*pathname!=0 && **pathname=='/') ++*pathname;
	const char *p=*pathname+1;
	while (*p!=0 && (*p!='/' || *(p-1)=='\\')) ++p;	// Now p points to the next separator or the end of the string
	strncpy(name,*pathname,p-*pathname);
	name[p-*pathname]=0;
	if (*p=='/') ++p;
	*pathname=p;
}

void get_path_and_name(const char *path,char *folder,char *name) {
	const char *p=path;
	while (*p!=0) ++p;
	while (p>path && (*p!='/' || *(p-1)=='\\')) --p;	// Now p points to the last path separator or the beginning of the string
	if (folder!=0) {
		strncpy(folder,path,p-path);
		folder[p-path]=0;
	}
	if (*p=='/') ++p;
	if (name!=0) strcpy(name,p);
}

/**
 * \brief Get the UTF-8 symbol associated with an HTML entity
 *
 * This function compares the string starting at p to all the entities of global array html_entities. If one is found to be the same, it returns the corresponding character in table utf_symbols. Otherwise it returns 0.
 * \param p String representing an HTML entity, does not include the starting amperstand
 * \param size Size of the HTML entity
 * \param symbol UTF-8 character associated with the entity if it is found
 * \return 0 if no character was found, 1 otherwise
 */
int get_entity(const char *p,size_t size,char *symbol) {
	int i=0;
	const char *q=p;
	const char *e=p+size;
	const char *r;
	while (i<num_html_entities) {
		r=html_entities[i];
		while (q!=e && *r!=0 && *q==*r) {++q;++r;}
		if (*r==0 && size==r-html_entities[i]) {strcpy(symbol,utf_symbols[i]);return 1;}
		++i;
	}
	return 0;
}

void html_to_text(const char *source,char *dest) {
	const char *p=source;
	char *q=dest;
	const char *r;
	char symbol[5];
	char *s;
	while (*p!=0) {
		if (*p!='&') *(q++)=*(p++);
		else {
			++p;
			r=p;
			while (*r!=0 && *r!=';') ++r;
			if (r==0) return;
			if (get_entity(p,r-p,symbol)) {
				s=symbol;
				while (*s!=0) *(q++)=*(s++);
			}
			p=r+1;
		}
	}
	*q=0;
}

void text_to_html(const char *source,char *dest) {
	const char *p=source;
	char *q=dest;
	const char *r;
	int i;
	while (*p!=0) {
		i=0;
		while (i<num_html_entities && strncmp(p,utf_symbols[i],strlen(utf_symbols[i]))!=0) ++i;
		if (i==num_html_entities) *(q++)=*(p++);
		else {
			r=html_entities[i];
			*(q++)='&';
			while (*r!=0) *(q++)=*(r++);
			*(q++)=';';
			p+=strlen(utf_symbols[i]);
		}
	}
	*q=0;
}

void free_item(Item *item) {
	if (item==0) return;
	free(item->name);
	free(item->path);
	free(item->requesturi);
	if (item->id!=0) {
		char name[200];
		get_local_file_name(item->id,name);
		unlink(name);
	}
	free(item);
}

Folder *create_folder(Folder *parent) {
	Folder *newfolder=malloc(sizeof(Folder));
	newfolder->file=malloc(sizeof(Item));
	newfolder->parent=parent;
	newfolder->elements=0;
	newfolder->next=0;
	newfolder->file->name=0;
	newfolder->file->path=0;
	newfolder->file->requesturi=0;
	newfolder->file->id=0;
	newfolder->file->size=0;
	newfolder->file->date=0;
	newfolder->file->updated=0;
	return newfolder;
}

void free_folder(Folder *folder) {
	if (folder==0) return;
	free_item(folder->file);
	free_folder(folder->elements);
	free_folder(folder->next);
	free(folder);
}

Folder *find_item(Folder *folder,char *name) {
	while (folder!=0 && strcmp(folder->file->name,name)!=0) folder=folder->next;
	return folder;	
}

Folder* add_element(Folder *folder,char *name,enum ItemType type,const char *path) {
	Folder *newfolder=create_folder(folder);
	newfolder->next=folder->elements;
	folder->elements=newfolder;
	newfolder->file->name=malloc(strlen(name)+1);
	strcpy(newfolder->file->name,name);
	newfolder->file->type=type;
	if (path!=0) {
		newfolder->file->path=malloc(strlen(path)+1);
		strcpy(newfolder->file->path,path);
	} else newfolder->file->path=0;
	return newfolder;
}

void remove_element(Folder *folder,char *name) {
	if (folder->elements==0) return;
	Folder *tmp;
	if (strcmp(folder->elements->file->name,name)==0) {
		tmp=folder->elements->next;
		folder->elements->next=0;
		free_folder(folder->elements);
		folder->elements=tmp;
		return;
	}
	Folder *children=folder->elements;
	while (children->next!=0 && strcmp(children->next->file->name,name)!=0) children=children->next;
	if (children->next==0) return;
	tmp=children->next;
	children->next=tmp->next;
	tmp->next=0;
	free_folder(tmp);
}

int get_id(Folder *folder,char *id) {
	if (folder==0) return -1;
	char *q=folder->file->path;
	while (*q!=0) ++q;	// Go to the end of the string
	while (q>=folder->file->path && (*q<'0' || *q>'9')) --q;	// Go to the last figure
	if (q<folder->file->path) return -1;
	char *p=q-1;
	while (p>=folder->file->path && *p>='0' && *p<='9') --p;
	if (p<folder->file->path) return -1;
	strncpy(id,p+1,q-p);
	id[q-p]=0;
	return 0;
}
